home *** CD-ROM | disk | FTP | other *** search
- /*
- File MyOSAComponentRoutines.c
-
-
-
- Copyright © 1992-1993 Apple Computer, Inc. All rights reserved.}
-
- This is a sample program to implement the OSA interface.
- In this sample program, the source is the same as the internal compiled form.
- So compile and decompile just consists of copying and rename, and this is very
- unlike other OSA implementation. However, there is a lot of scripting language
- which just interprets the source and this sample program can be useful.
-
- Ported over to C 9/20/95
- R.Silva
-
-
-
- */
-
- #ifdef THINK_C
- #define applec
- #endif
-
- //#include "myHeaders.h"
-
- #include <Errors.h>
- #include <TextEdit.h>
- #include <Components.h>
- #include <OSAComp.h>
-
- #include "MyOSAComponent.h"
- #include "MyOSAComponentRoutines.h"
-
-
- //prototyping
- ComponentResult FindSlotAndPutIt(GlobalsHandle globals, AEDesc theDesc,long *slotID);
- long FindScriptIDSlot(GlobalsHandle globals);
- void NukeIt(AEDesc *theDesc);
- void ClearErrorDesc(GlobalsHandle globals);
- OSErr TextToStxt(AEDesc textDesc, AEDesc *result);
- ComponentResult TryDoScript(GlobalsHandle globals, AEDesc *scriptData, int *num);
- ComponentResult ActualDoScript(GlobalsHandle globals, AEDesc *scriptData, AEDesc *result);
- int myStrcmp( char * firstString, char * secString);
- OSErr myStrcat( char * firstString, char * secString);
- int myStrlen( char * theString);
-
- /* ------------------------------------------------------------------------- */
- // put a desc into a slot, if slotID starts as 0 find a new slot,
- // otherwise reuse the slot ID
- //
- ComponentResult FindSlotAndPutIt(GlobalsHandle globals, AEDesc theDesc, long *slotID)
- {
- OSErr err = noErr;
- AEDesc *oldDesc;
- long mySlot;
-
- mySlot = *slotID;
- HLock((Handle)globals);
- if( theDesc.dataHandle == nil){
- mySlot = 0;
- err = memFullErr;
- }
- else{
- if( mySlot == 0 ){
- mySlot = FindScriptIDSlot(globals); //find an empty slot
- }
- else{
- //reuse an existing slot, we first dispose the old content
- oldDesc = &((*globals)->scriptIDSlot[mySlot]);
- AEDisposeDesc(oldDesc);
- }
- if( slotID != 0 ) {
- //keep the same handle
- ((*globals)->scriptIDSlot[mySlot] ).dataHandle = theDesc.dataHandle;
- ((*globals)->scriptIDSlot[mySlot] ).descriptorType = theDesc.descriptorType;
- }
- else{
- err = memFullErr; //no slot available, treat it as memory error because
- //in a more realistic program we would expand the slots
- mySlot = 0;
- //get rid of it since it wasnt used
- AEDisposeDesc(&theDesc);
- }
- }
- HUnlock((Handle)globals);
- *slotID = mySlot;
-
- return err;
- }
- //search for a empty slot and return the slot ID, return 0 if none is available
- //start at the number 1 slot, zero means "get a new slot"
- //
- long FindScriptIDSlot(GlobalsHandle globals)
- {
- int i;
-
- for( i = 1; i< MaxIDSlot ; i++) {
- if( ((*globals)->scriptIDSlot)[i].dataHandle == nil ) {
- break;
- }
- }
- if(i == MaxIDSlot) i = 0;
- return i;
- }
- //
- //make a copy, strip the trailer and put it into a slot
- //
- pascal ComponentResult DoOSALoad(Handle myGlobals, AEDesc *scriptData,
- long modeFlags, OSAID *resultingScriptID)
- {
- ComponentResult err;
- AEDesc descCopy;
- DescType itsType;
- GlobalsHandle globals;
-
-
- globals = (GlobalsHandle) myGlobals;
-
- err = errOSABadStorageType;
- if ((*scriptData).descriptorType == kOSAGenericScriptingComponentSubtype) {
- if( OSAGetStorageType((*scriptData).dataHandle, &itsType) == noErr ) {
- if( itsType == MySignature ) {
- err = AEDuplicateDesc(scriptData, &descCopy);
- if( err == noErr) { err = OSARemoveStorageType(descCopy.dataHandle); }
- //internally we store as type 'SMPL'
- descCopy.descriptorType = MySignature;
- //we want a new OSAID
- resultingScriptID = 0;
- err = FindSlotAndPutIt(globals, descCopy, (long *) resultingScriptID);
- }
- }
- }
- return err;
- }
- //make a null descriptor
- void NukeIt(AEDesc *theDesc)
- {
- theDesc->descriptorType = typeNull;
- theDesc->dataHandle = nil;
- }
-
- //make a copy of content in the slot and add trailer
- //
- pascal ComponentResult DoOSAStore(GlobalsHandle globals, OSAID scriptID,
- DescType desiredType,long modeFlags,
- AEDesc *resultingScriptData)
- {
- ComponentResult err;
-
- NukeIt(resultingScriptData);
- if( (scriptID <= 0) || (scriptID > MaxIDSlot - 1) ) {
- err = errOSAInvalidID;
- }
- else{
- HLock((Handle)globals);
- err = AEDuplicateDesc( &((*globals)->scriptIDSlot[scriptID]),resultingScriptData) ;
- HUnlock((Handle)globals);
- if( err != noErr ) {
- NukeIt(resultingScriptData);
- }
- if( (*resultingScriptData).dataHandle == nil){
- err = errOSAInvalidID;
- }
- else{
- err = OSAAddStorageType( (*resultingScriptData).dataHandle, (*resultingScriptData).descriptorType);
- if( err == noErr) {
- (*resultingScriptData).descriptorType = kOSAGenericScriptingComponentSubtype;
- }
- else {
- AEDisposeDesc(resultingScriptData);
- NukeIt(resultingScriptData);
- }
- }
- }
- return err;
- }
- //fetch the content of the error descriptor
- //
- pascal ComponentResult DoOSAScriptError(GlobalsHandle globals, OSType selector,
- DescType desiredType, AEDesc *resultingErrorDescription)
- {
- ComponentResult err;
- long i;
- AERecord aRec ;
- AEDesc *myErrorDesc ;
- int errNum;
-
- NukeIt(resultingErrorDescription);
- if( selector == kOSAErrorNumber ) {
- HLock((Handle)globals);
- errNum = (*globals)->errorNumber;
- HUnlock((Handle)globals);
- err = AECoercePtr(typeShortInteger, &errNum, sizeof(int), desiredType, resultingErrorDescription);
- }
- else if ( selector == kOSAErrorMessage) {
- HLock((Handle)globals);
- myErrorDesc = &((*globals)->errorDesc);
- if( (desiredType == typeChar) || (desiredType == typeWildCard) ){
- err = AEDuplicateDesc(myErrorDesc, resultingErrorDescription);
- }
- else if ( desiredType == 'STXT') {
- err = TextToStxt(*myErrorDesc, resultingErrorDescription);
- }
- else {
- err = AECoerceDesc(myErrorDesc, desiredType, resultingErrorDescription);
- }
- HUnlock((Handle)globals);
- }
- else if( selector == kOSAErrorRange) {
- //in this simple example, we make the error range to include everything
- err = AECreateList(nil, 0, true, &aRec);
- if( err == noErr) {
- i = 0;
- AEPutKeyPtr(&aRec, keyOSASourceStart, typeLongInteger, &i, sizeof(i));
- i = 30000;
- AEPutKeyPtr(&aRec, keyOSASourceEnd, typeLongInteger, &i, sizeof(i) );
- if( desiredType == typeAERecord ) {
- err = AEDuplicateDesc(&aRec, resultingErrorDescription);
- }
- else {
- if( desiredType == typeWildCard ){
- desiredType = typeOSAErrorRange;
- err = AECoerceDesc(&aRec, desiredType, resultingErrorDescription);
- }
- }
- AEDisposeDesc(&aRec);
- }
- }
- else{
- err = errOSABadSelector;
- }
- return err;
- }
- //
- //dispose the descriptor in the slot I check whether the dataHandle is nil first
- //
- pascal ComponentResult DoOSADispose(GlobalsHandle globals,
- OSAID scriptID)
- {
- if( (scriptID > 0) && (scriptID < MaxIDSlot) ) {
- HLock((Handle)globals);
- if(((*globals)->scriptIDSlot[scriptID]).dataHandle != nil ){
- AEDisposeDesc(&((*globals)->scriptIDSlot[scriptID]));
- ((*globals)->scriptIDSlot[scriptID]).dataHandle = nil;
- }
- HUnlock((Handle)globals);
- }
- return noErr;
- }
- //
- //since in this sample program, internal form is the same as source form
- //except for the descriptor type, we can just call CompileExecute
- pascal ComponentResult DoOSAExecute(GlobalsHandle globals, OSAID compiledScriptID,
- OSAID contextID, long modeFlags, OSAID *resultingScriptValueID)
- {
- AEDesc myDesc;
- ComponentResult err;
-
- *resultingScriptValueID = 0;
- if( (compiledScriptID <= 0) || (compiledScriptID > MaxIDSlot - 1) )
- return errOSAInvalidID;
- else{
- HLock((Handle)globals);
- err = AEDuplicateDesc(&((*globals)->scriptIDSlot[compiledScriptID]), &myDesc);
- HUnlock((Handle)globals);
- if(err == noErr){
- err = DoOSACompileExecute(globals, &myDesc,
- contextID, modeFlags, resultingScriptValueID);
- AEDisposeDesc(&myDesc);
- }
- }
- return err;
- }
- //
- //in this program, we have no special form for display so just coerce it
- //
- pascal ComponentResult DoOSADisplay(GlobalsHandle globals, OSAID scriptValueID,
- DescType desiredType, long modeFlags,
- AEDesc *resultingText)
- {
-
- return DoOSACoerceToDesc(globals, scriptValueID, desiredType, modeFlags, resultingText);
- }
- //
- //since internal form is same as source, just change the dataType and call TryDoScript,
- //if it compiles then just store it
- pascal ComponentResult DoOSACompile(GlobalsHandle globals, AEDesc *sourceData,
- long modeFlags, OSAID *resultingCompiledScriptID)
- {
- ComponentResult err;
- AEDesc descCopy;
- int num;
-
- if( (*sourceData).descriptorType == typeChar) {
- (*sourceData).descriptorType = MySignature;
- err = TryDoScript(globals, sourceData, &num);
- if( err == noErr ) {
- err = AEDuplicateDesc(sourceData, &descCopy);
- if(err == noErr){
- err = FindSlotAndPutIt(globals, descCopy, (long *) resultingCompiledScriptID);
- }
- }
- }
- else{
- err = errOSABadStorageType;
- }
- return err;
- }
- //in this sample program, source is same as internal form and
- //there is no special formatting, so just call coerce
- //
- pascal ComponentResult DoOSAGetSource(GlobalsHandle globals, OSAID scriptID,
- DescType desiredType, AEDesc *resultingSourceData)
- {
- return DoOSACoerceToDesc(globals, scriptID, desiredType, 0, resultingSourceData);
- }
- //
- //just store a copy into the slot
- //
- pascal ComponentResult DoOSACoerceFromDesc(GlobalsHandle globals, AEDesc *scriptData,
- long modeFlags, OSAID *resultingScriptValueID)
- {
-
- ComponentResult err;
- AEDesc descCopy;
-
- err = AEDuplicateDesc(scriptData, &descCopy);
- if( err == noErr ) {
- *resultingScriptValueID = 0; //put it in a new slot
- err = FindSlotAndPutIt(globals, descCopy, (long *) resultingScriptValueID);
- }
- return err;
- }
-
- //fetch from the slot and coerce it, if it is source we rename the
- //type because internal form is same as the source text
- //
- pascal ComponentResult DoOSACoerceToDesc(GlobalsHandle globals, OSAID scriptValueID,
- DescType desiredType, long modeFlags, AEDesc *result)
- {
- ComponentResult err;
- AEDesc myScriptValue;
-
- if( (scriptValueID <= 0) || (scriptValueID > MaxIDSlot - 1)) {
- err = errOSAInvalidID;
- }
- else {
- HLock((Handle)globals);
- err = AEDuplicateDesc( &((*globals)->scriptIDSlot[scriptValueID]),&myScriptValue );
- HUnlock((Handle)globals);
- if( err == noErr ){
- if( myScriptValue.descriptorType == MySignature ){
- myScriptValue.descriptorType = typeChar;
- }
- if( myScriptValue.descriptorType == desiredType ) {
- err = AEDuplicateDesc(&myScriptValue, result);
- }
- else if( desiredType == 'STXT') {
- err = TextToStxt(myScriptValue, result);
- }
- else {
- err = AECoerceDesc(&myScriptValue, desiredType, result);
- }
- AEDisposeDesc(&myScriptValue);
- }
- }
- return err;
- }
-
- //strip the trailer, execute it and put back the trailer
- //there is chance we cannot restore the original form although we are try our best
- //this really calls for a GetScriptDataSize call in OSAComp
- pascal ComponentResult DoOSALoadExecute(GlobalsHandle globals, AEDesc *scriptData,
- OSAID contextID, long modeFlags,
- OSAID *resultingScriptValueID )
- {
- ComponentResult err;
- DescType itsType;
-
- err = errOSABadStorageType;
- if( (*scriptData).descriptorType == kOSAGenericScriptingComponentSubtype ) {
- if( OSAGetStorageType((*scriptData).dataHandle, &itsType) == noErr ) {
- if( itsType == MySignature ) {
- err = OSARemoveStorageType((*scriptData).dataHandle);
- if( err == noErr ) {
- err = DoOSACompileExecute(globals, scriptData, 0, 0, resultingScriptValueID);
- if( OSAAddStorageType((*scriptData).dataHandle, MySignature) != noErr ) {
- //we are in deep trouble, we changed scriptData and cannot put it back
- //dispose result to get back the memory
- DoOSADispose(globals, *resultingScriptValueID);
- resultingScriptValueID = 0;
- //now try again
- OSAAddStorageType((*scriptData).dataHandle, MySignature);
- err = memFullErr; //fail because we don't have enough memory
- }
- }
- }
- }
- }
- return err;
- }
- //
- //since source is same as internal form, just execute it and store the result
- //
- pascal ComponentResult DoOSACompileExecute(GlobalsHandle globals, AEDesc *sourceData,
- OSAID contextID, long modeFlags,
- OSAID *resultingScriptValueID)
- {
- ComponentResult err;
- AEDesc resultDesc, anoDesc;
-
- err = AEDuplicateDesc(sourceData, &anoDesc);
- if( err == noErr ){
- anoDesc.descriptorType = MySignature;
- err = ActualDoScript(globals, &anoDesc, &resultDesc);
- if( err == noErr ) {
- err = FindSlotAndPutIt(globals, resultDesc,(long *) resultingScriptValueID);
- }
- AEDisposeDesc(&anoDesc);
- }
- return err;
- }
-
- //
- //since source is same as internal form, just execute it and return the result
- //
- pascal ComponentResult DoOSADoScript(GlobalsHandle globals, AEDesc *sourceData, OSAID contextID,
- DescType desiredType, long modeFlags, AEDesc *resultingText )
- {
- ComponentResult err;
- AEDesc resultDesc;
-
- (*sourceData).descriptorType = MySignature;
- NukeIt(resultingText);
- err = ActualDoScript(globals, sourceData, &resultDesc);
- if( err == noErr) {
- if( (desiredType == resultDesc.descriptorType) || (desiredType == typeWildCard) ){
- err = AEDuplicateDesc( &resultDesc, resultingText);
- }
- else {
- if( desiredType == 'STXT') {
- err = TextToStxt(resultDesc, resultingText);
- }
- else {
- err = AECoerceDesc(&resultDesc, desiredType, resultingText);
- AEDisposeDesc(&resultDesc);
- }
- }
- }
- return err;
- }
-
- //
- //context is not used in this sample program
- //
- pascal ComponentResult DoOSAMakeContext(GlobalsHandle globals, AEDesc *contextName,
- OSAID parentContext, OSAID *resultingContextID )
- {
- *resultingContextID = 0;
- return noErr;
- }
-
- //
- //return the name of the scripting component
- //
- pascal OSAError DoOSAScriptingComponentName(GlobalsHandle globals,
- AEDesc *resultingScriptingComponentName)
- {
- char aStr[] = "SampleScript";
-
- return AECreateDesc(typeChar, &aStr[0], 12, resultingScriptingComponentName);
- }
-
- //
- //execute the script and return a number or set the error result
- //
- ComponentResult ActualDoScript(GlobalsHandle globals, AEDesc *scriptData,
- AEDesc *result)
- {
-
- int num;
- OSErr err;
-
- err = TryDoScript(globals, scriptData, &num);
- if( err == noErr) { // THEN
- err = AECreateDesc(typeShortInteger, &num, sizeof(int), result);
- }
- return err;
- }
-
- //try to compile the text and return the result
- //we just try to translate one, two, three etc into a number in this simple example
- //
- ComponentResult TryDoScript(GlobalsHandle globals, AEDesc *scriptData, int *num)
- {
- char aStr[256] ;
- char myDigits[10][20] = {"ONE","TWO", "THREE", "FOUR", "FIVE", "SIX", "SEVEN", "EIGHT", "NINE", "TEN" };
- OSErr err;
- int i;
- short myLong;
- char myComment[256] = "Cannot understand ";
- StringPtr thePtr;
-
- *num = 0;
- if( (*scriptData).descriptorType == MySignature ) {
- HLock((*scriptData).dataHandle);
- myLong = GetHandleSize((*scriptData).dataHandle);
- BlockMove(*((*scriptData).dataHandle), &aStr[0],myLong);
- aStr[myLong] = '\0';
- HUnlock((*scriptData).dataHandle);
-
- for(i=0; i < 10; i++){
- if(myStrcmp(aStr, myDigits[i])){
- *num = i + 1;
- break;
- }
- }
- ClearErrorDesc(globals);
- if( *num == 0){
- if(myStrcat(myComment, aStr) == noErr){
- err = errOSAScriptError;
- HLock((Handle)globals);
- (*globals)->errorNumber = err;
- PtrToXHand( &myComment[0], ((*globals)->errorDesc).dataHandle, myStrlen( myComment) );
- HUnlock((Handle)globals);
- }
- }
- else {
- err = noErr;
- }
- }
- else{
- err = errOSABadStorageType;
- }
- return err;
- }
-
-
- typedef struct
- {
- int scrpNStyles;
- ScrpSTElement scrpStyle;
- }myStyleRec ;
-
-
- //
- //convert TEXT to styled text
- //
- OSErr TextToStxt(AEDesc textDesc, AEDesc *result)
- {
- OSErr err;
- AERecord theRec;
- myStyleRec myStyle;
-
- (*result).dataHandle = nil;
- myStyle.scrpNStyles = 1;
- myStyle.scrpStyle.scrpStartChar = 0;
- myStyle.scrpStyle.scrpHeight = 16;
- myStyle.scrpStyle.scrpAscent = 12;
- myStyle.scrpStyle.scrpFont = 1;
- myStyle.scrpStyle.scrpFace = bold;
- myStyle.scrpStyle.scrpSize = 12;
- myStyle.scrpStyle.scrpColor.red = 0;
- myStyle.scrpStyle.scrpColor.green = 0;
- myStyle.scrpStyle.scrpColor.blue = 0;
-
- err = AECreateList(nil, 0, true, &theRec);
- if( err == noErr){
- err = AEPutKeyPtr(&theRec, 'ksty', 'styl', &myStyle, sizeof(myStyle));
- if( err == noErr) {
- err = AEPutKeyDesc(&theRec, 'ktxt', &textDesc);
- }
- if( err == noErr){
- err = AECoerceDesc(&theRec, 'STXT', result);
- }
- AEDisposeDesc(&theRec);
- }
- return err;
- }
-
- //
- //clean up the error message
- //
- void ClearErrorDesc(GlobalsHandle globals)
- {
- HLock((Handle)globals);
- (*globals)->errorNumber = noErr;
- SetHandleSize(((*globals)->errorDesc).dataHandle, 0);
- HUnlock((Handle)globals);
- }
-
- //
- //added this since the documentation says its required
- //returning noErr
- pascal ComponentResult DoOSASetScriptInfo(GlobalsHandle globals, OSAID scriptID,
- OSType selector, long value)
- {
- ComponentResult myResult = noErr;
-
- if( selector == kOSAScriptIsModified ){
- myResult = noErr;
- }
- return myResult;
-
- }
-
- //
- //added this since the documentation says its required
- //
- pascal ComponentResult DoOSAGetScriptInfo(GlobalsHandle globals, OSAID scriptID,
- OSType selector, long * value)
- {
- ComponentResult myResult = noErr;
-
- switch ( selector ) {
-
- case kOSAScriptIsModified:
- *value = 1;
- break;
-
- case kOSAScriptIsTypeCompiledScript:
- *value = 1;
- break;
-
- case kOSAScriptIsTypeScriptValue:
- *value = 1;
- break;
-
- case kOSAScriptIsTypeScriptContext:
- *value = 1;
- break;
-
- case kOSAScriptBestType:
- *value = (long) typeChar;
- break;
-
- case kOSACanGetSource:
- *value = 1;
- break;
-
- default :
- myResult = paramErr;
- }
- return myResult;
- }
-
- //
- //if two strings are the same return 1 otherwise return 0
- //make them case independent
- //
- int myStrcmp( char * firstString, char * secString)
- {
- int i=0;
- short myShort, aShort;
-
-
- aShort = (short) ('a' - 'A' );
- while( firstString[i] != '\0' ){
- myShort = (short) ( firstString[i] - secString[i] );
- if( ( (myShort % aShort) == 0 )&&(secString[i] != '\0')){
- i++;
- }
- else{
- return 0;
- }
- }
-
- if(secString[i] != '\0')
- return 0;
- else
- return 1;
- }
-
- //
- //concatenate two strings the second to the first
- //
- OSErr myStrcat( char * firstString, char * secString)
- {
- int i = 0;
- int j = 0;
- OSErr myErr;
-
- while( (firstString[i] != '\0') && i < 100){
- i++;
- }
- if( i == 100){
- myErr = 1; //some error
- return myErr;
- }
- while( (secString[j] != '\0') && j < 100){
- firstString[i+j] = secString[j];
- j++;
- }
- if( j == 100){
- myErr = 1; //some error
- return myErr;
- }
- firstString[i+j] = '\0';
- return noErr;
- }
-
- //
- // get the string length
- //
- int myStrlen( char * theString)
- {
- int i=0;
-
- while( (theString[i] != '\0') && (i< 200) ){
- i++;
- }
- return i+1;
- }
-